package com.joker.microstoremanager.service;

import com.google.common.base.Strings;
import com.joker.microstoremanager.context.MessageHolder;
import com.joker.microstoremanager.context.UserContext;
import com.joker.microstoremanager.model.*;
import com.joker.microstoremanager.repository.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.async.DeferredResult;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.Date;
import java.util.List;

/**
 * The type Goods service.
 */
@Service
@Slf4j
public class GoodsService {
    @Resource
    private GoodsRepository goodsRepository;
    @Resource
    private ShopRepository shopRepository;
    @Resource
    private HistoryRepository historyRepository;
    @Resource
    private TagRepository tagRepository;
    @Resource
    private GoodsTagRepository goodsTagRepository;
    @Resource
    private BrandRepository brandRepository;

    /**
     * Find all tags list.
     *
     * @param user the user
     * @return the list
     */
    public List<Tag> findAllTags(MicroShop user) {
        return tagRepository.findByShop(user);
    }

    /**
     * Add type.
     *
     * @param user the user
     * @param g    the g
     */
    public void addType(MicroShop user, Goods g) {
        Goods goods;
        if(g.getId()!=null){
            goods = goodsRepository.findOne(g.getId());
            goods.setName(g.getName());
            goods.setPosition(g.getPosition());
            goods.setSerialNo(g.getSerialNo());
            goods.setCnt(g.getCnt());
            goodsRepository.save(goods);
        }else{
            String trimName = g.getName().replace(" ","").toLowerCase();
            List<Brand> brands = brandRepository.findAll();
            for(Brand b:brands){
                if(trimName.contains(b.getName().replace(" ","").toLowerCase())){
                    g.setBrand(b);
                }
            }
            g.setShop(user);
            goods = goodsRepository.save(g);
            List<Tag> tags = this.findAllTags(user);
            for(Tag t:tags){
                if(trimName.contains(t.getName().replace(" ","").toLowerCase())){
                    GoodsTagRelation relation = new GoodsTagRelation();
                    relation.setGoods(goods);
                    relation.setTag(t);
                    goodsTagRepository.save(relation);
                }
            }
        }
    }

    /**
     * Find all goods page.
     *
     * @param user    the user
     * @param request the request
     * @return the page
     */
    public Page<Goods> findAllGoods(MicroShop user, Pageable request) {
        return goodsRepository.findByShop(user.getId(), request);
    }

    /**
     * Sku change string.
     *
     * @param serialNo the serial no
     * @param action   1入库 2出库
     * @param user
     * @param goodsId  the goods id
     * @return the string
     */
    @SuppressWarnings("unchecked")
    public String skuChange(String serialNo, Integer action, MicroShop user, Long goodsId) {
        Goods g;
        if(goodsId != null && goodsId.compareTo(0L)>0){
            //提供了商品号，说明要指定该商品的条码
            g = goodsRepository.findOne(goodsId);
            g.setSerialNo(serialNo);
        }else{
            g = goodsRepository.findBySerialNoAndShopId(serialNo,user.getId());
            if(g == null){
                log.error("条码不存在并且未指定商品！");
                return "条码不存在并且未指定商品！";
            }
        }
        DeferredResult deferredResult = MessageHolder.holder.get(user.getId());
        if(deferredResult != null){
            deferredResult.setResult("ok");
        }

        InOutHistory history = new InOutHistory();
        history.setShopId(user.getId());
        history.setOperateType(action);
        history.setOpDate(new Date());
        history.setGoods(g);
        history.setSerialNo(serialNo);
        historyRepository.save(history);

        if(action.equals(Goods.Action.IMPORT)){
            g.setCnt(g.getCnt()+1);
            goodsRepository.save(g);
            return "入库完成";
        }else if(action.equals(Goods.Action.EXPORT)){
            g.setCnt(g.getCnt()-1);
            goodsRepository.save(g);
            return "出库完成";
        }
        return "不是出库也不是入库？什么都没有发生";
    }

    /**
     * Init default shop.
     */
    @PostConstruct
    public void initDefaultShop() {
        MicroShop shop = shopRepository.findOne(1L);
        if (shop == null) {
            shop = new MicroShop();
            shop.setId(1L);
            shop.setName("LittleM");
            shop.setUsername("littlem");
            shop.setPassword("littlem");
            shopRepository.save(shop);
        }
    }

    /**
     * Find history page.
     *
     * @param shop  the shop
     * @param start the start
     * @param end   the end
     * @param type  the type
     * @param page  the page
     * @return the page
     */
    public Page<InOutHistory> findHistory(MicroShop shop, Date start, Date end, Integer type, Pageable page) {
        Page<InOutHistory> histories;
        if (type != null) {
            histories = historyRepository.findByShopIdAndOpDateBetweenAndOperateType(shop.getId(),start, end, type, page);
        } else {
            histories = historyRepository.findByShopIdAndOpDateBetween(shop.getId(),start, end, page);
        }
        return histories;
    }

    /**
     * Recategory.
     *
     * @param shop the shop
     */
    @Transactional
    public void recategory(MicroShop shop) {
        MicroShop user = UserContext.getUser();
        goodsTagRepository.deleteByShop(user.getId());
        List<Tag> tags = this.findAllTags(shop);
        Iterable<Goods> goods = goodsRepository.findByShopId(shop.getId());
        tags.forEach(tag -> goods.iterator().forEachRemaining(goods1 -> {
            if (goods1.getName().toLowerCase().contains(tag.getName().toLowerCase())) {
                GoodsTagRelation relation = new GoodsTagRelation();
                relation.setGoods(goods1);
                relation.setTag(tag);
                goodsTagRepository.save(relation);
            }
        }));

        List<Brand> brands = brandRepository.findAll();
        goods.forEach(g -> {
            if (g.getBrand() == null) {
                for (Brand b : brands) {
                    String trimName = g
                            .getName()
                            .replace(" ", "")
                            .toLowerCase();
                    if ((!Strings.isNullOrEmpty(b.getChineseName()) && trimName
                            .contains(b.getChineseName().replace(" ", "").toLowerCase()))
                            ||
                            (!Strings.isNullOrEmpty(b.getEnglishName())
                                    &&
                                    trimName.contains(b.getEnglishName().replace(" ", "").toLowerCase()))) {
                        g.setBrand(b);
                        break;
                    }
                }
            }
        });
        goodsRepository.save(goods);
    }


    /**
     * Find goods by tag id page.
     *
     * @param tagId   the tag id
     * @param request the request
     * @return the page
     */
    public Page<Goods> findGoodsByTagId(Long tagId, Pageable request) {
        return goodsRepository.findByTags(tagId, request);
    }

    /**
     * Delete goods.
     *
     * @param goodsId the goods id
     */
    public void deleteGoods(Long goodsId){
        goodsTagRepository.deleteByGoodsId(goodsId);
        goodsRepository.delete(goodsId);
    }
}
